//! @author Adam Emil Skoog
//! @date   2011-12-24

#include "EventReceiver.h"
#include "Component.h"

namespace kedja
 {
	/**
	 * Destroys the event receiver with the specified address and deallocates it entirely.
	 *
	 * @param receiver A pointer to the receiver to remove.
	 * @return Whether the receiver existed and thus was removed.
	 */
	bool EventReceiver::destroyEventReceiver(EventReceiver *const receiver)
	 {
		// There must have been an initialisation.
		assert(static_cast<bool>(eventReceivers));

		if (eventReceivers)
		 {
			for (unsigned i(0); i < eventReceivers->size(); ++ i)
			 {
				if ((*eventReceivers)[i] == receiver)
				 {
					eventReceivers->erase(eventReceivers->begin() + i);
					delete receiver;
					return true;
				 }
			 }
		 }

		return false;
	 }

	/**
	 * Returns the event receiver at the specified index in the list of created
	 * event receivers, if that index is valid.
	 *
	 * @param index The index from which to retrieve the event receiver.
	 * @return A pointer to the event receiver at the specified index.
	 */
	EventReceiver *const EventReceiver::getEventReceiver(const unsigned &index)
	 {
		// There must have been an initialisation.
		assert(static_cast<bool>(eventReceivers));

		// Make sure there are any parents at all.
		assert((eventReceivers->size() > 0));

		// Validate the index.
		assert((index < eventReceivers->size()));

		if (eventReceivers)
			if (eventReceivers->size() > 0)
			if (index < eventReceivers->size())
				return (*eventReceivers)[index];

		return NULL;
	 }

	/**
	 * Returns the number of created event receivers in the list.
	 *
	 * @return The number of event receivers.
	 */
	const unsigned EventReceiver::getEventReceiverCount()
	 {
		// There must have been an initialisation.
		assert(static_cast<bool>(eventReceivers));

		if (eventReceivers)
			return eventReceivers->size();
	 }

	/**
	 * Returns the parent at the specified index.
	 *
	 * @param index The index of the parent to fetch.
	 * @return The parent at the specified index.
	 */
	Component *const EventReceiver::getParent(const unsigned &index) const
	 {
		// Make sure there are any parents at all.
		assert((parents.size() > 0));

		// Validate the index.
		assert((index < parents.size()));

		if (parents.size() > 0)
			if (index < parents.size())
				return parents[index];

		return NULL;
	 }

	/**
	 * Returns whether the specified component has registered this event receiver.
	 *
	 * @param component Component to check against.
	 * @return Whether the component has registered this event receiver.
	 */
	bool EventReceiver::isRegisteredToComponent(Component *const component) const
	 {
		for (unsigned i(0); i < getParentCount(); ++ i)
			if (getParent(i) == component)
				return true;

		return false;
	 }

	/**
	 * Returns the number of parents linked with this event receiver.
	 *
	 * @return The number of parents.
	 */
	const unsigned EventReceiver::getParentCount() const
	 {
		return parents.size();
	 }

	/**
	 * Initialises the event system. This is handled by the component class.
	 */
	void EventReceiver::initialise()
	 {
		// Prohibit double initialisation.
		assert(!static_cast<bool>(eventReceivers));

		if (!eventReceivers)
			eventReceivers = new std::vector<EventReceiver *>;
	 }

	/**
	 * Deinitialises the event system. This is handled by the component class.
	 */
	void EventReceiver::deinitialise()
	 {
		// Prohibit double deinitialisation.
		assert(static_cast<bool>(eventReceivers));

		if (eventReceivers)
		 {
			for (unsigned i(0); i < eventReceivers->size(); ++ i)
				delete (*eventReceivers)[i];

			eventReceivers->clear();
			delete eventReceivers;
			eventReceivers = NULL;
		 }
	 }

	/**
	 * Registers a parent component to the event receiver. This is done by the
	 * component itself, and thus the function is private.
	 *
	 * @param component The parent component to register.
	 */
	void EventReceiver::registerParent(Component *const component)
	 {
		const bool notRegistered(!isRegisteredToComponent(component));

		// Make sure that this parent has not already been registered.
		assert(notRegistered);

		// Make sure that the parent is allocated.
		assert(static_cast<bool>(component));

		if (notRegistered && component)
			parents.push_back(component);
	 }

	/**
	 * Deregisters the parent at the specified memory address. This is done by the
	 * component itself, and thus the function is private.
	 *
	 * @param component The parent component to deregister.
	 */
	void EventReceiver::deregisterParent(Component *const component)
	 {
		const bool registered(isRegisteredToComponent(component));

		// Make sure that this parent has been registered.
		assert(registered);

		if (registered)
		 {
			for (unsigned i(0); i < getParentCount(); ++ i)
			 {
				if (parents[i] == component)
				 {
					parents.erase(parents.begin() + i);
					return;
				 }
			 }
		 }
	 }

	/**
	 * Destructor.
	 */
	EventReceiver::~EventReceiver()
	 {
		// Deregister components.
		while (getParentCount() > 0)
			getParent(0)->deregisterEventReceiver(this);
	 }

	// Define static variables.
	std::vector<EventReceiver *> *EventReceiver::eventReceivers = NULL;
 }
